#include "AugPourcent.h"

//#include "ADD.h"
#include "Classe.h"

#include <QtGui/QSpinBox>
#include <QtGui/QGroupBox>
#include <QtGui/QLabel>
#include <QtGui/QLCDNumber>
#include <QtGui/QVBoxLayout>
#include <QtGui/QGridLayout>
#include <QtGui/QPushButton>

using namespace std;

/**
 * Constructeur par défault. Détermine la Classe et l'éventuel parent
 * du QDialog. On récupère également une information sur le status de
 * la Classe : phase de création ou passage de niveau.
 *
 * @param classe pointeur sur la Classe que l'on veut faire évoluer.
 * @param lvlUp valeur booléenne déterminant si il s'agit d'un passage
 * de niveau (\e true, valeur par défaut) ou de la création de la
 * Classe (\e false).
 * @param parent pointeur sur le widget parent (orphelin par défaut)
 */
AugPourcent::AugPourcent(Classe* classe, const bool& lvlUp, QWidget *parent)
  : BaseDialog( QString::fromUtf8("AugPourcent"), parent ),
    creation( !lvlUp ), dimension( 0 ), total( 0 ), PP( 0 )
{
  mClasse = classe;

  PP = static_cast<int>( mClasse -> pourcent( lvlUp ) );

  nbrPP = new QLCDNumber( this );

  nbrPP -> setSegmentStyle(QLCDNumber::Flat);

  nbrPP -> display( static_cast<int>( PP ) );

  boite = new QGroupBox( trUtf8("Compétences à améliorer"), this );

  prepareBoutons();
  
  prepareAffichage();

  fenetreLayout -> addWidget( nbrPP );

  fenetreLayout -> addWidget( boite );

  setFenetreLayout();
}

/**
 * Constructeur de copie. Il faut ici faire attention uniquement à
 * copier le pointeur sur l'instance de la Classe à modifier, le reste
 * étant automatiquemen géré par setFenetreLayout().
 *
 * @param pour instance de AugPourcent à dupliquer.
 */
AugPourcent::AugPourcent(const AugPourcent& pour)
  : BaseDialog( pour ), creation( ! pour.creation ), dimension( 0 ), total( 0 ),
    PP( 0 )
{
  mClasse = pour.mClasse;

  PP = static_cast<int>( mClasse -> pourcent( creation ) );

  nbrPP = new QLCDNumber( this );

  nbrPP -> setSegmentStyle(QLCDNumber::Flat);

  nbrPP -> display( static_cast<int>( PP ) );

  boite = new QGroupBox( trUtf8("Compétences à améliorer"), this );

  prepareBoutons();
  
  prepareAffichage();

  fenetreLayout -> addWidget( nbrPP );

  fenetreLayout -> addWidget( boite );

  setFenetreLayout(); 
}

/**
 * Destructeur. On laisse ici travailler le mécanisme natif Qt.
 */
AugPourcent::~AugPourcent()
{}

/**
 * Permet d'afficher le QDialog et de répartir les points.
 *
 * @return StatusCode, dont l'etat est \e true si on valide la
 * sélection, \e false sinon.
 */
StatusCode AugPourcent::pointsRepartis()
{
  this -> exec();

  return StatusCode(OK);
}

/**
 * Construit la liste de QSpinBox à partir des compétences de classe
 * et des valeurs initiales. Chaque QSinBox est ensuite connecté à la
 * méthode changerValeur().
 *
 * Le niveau de sortie est paramétré par BaseDialog::interne :\n
 * - \e FUNC  affiche les messages de début et de fin de méthode.\n
 * - \e DEBUG affiche le nom et la valeur initiale de chaque compétence.
 */
void AugPourcent::prepareAffichage()
{
  /*Debug::*/empileNiveau( &interne );
  func() << "AugPourcent::prepareAffichage -> début" << endmsg;

  unsigned int taille( mClasse -> tailleCompetences() ), i;

  CompetenceClasse tmp;

  QGridLayout *boiteLayout = new QGridLayout( boite );

  labels.clear();
  valeurs.clear();
  anciennesVal.clear();

  for (i = 0; i < taille; i++)
    {
      tmp = mClasse -> competenceNumero( mClasse -> numCompetence( i ) );
      if ( tmp . pourcentage() )
	{
	  labels.push_back( new QLabel( QString::fromUtf8(tmp.nom().c_str()),
					this ) );
	  valeurs.push_back( new QSpinBox( this) );
	  valeurs.back() -> setMinimum( mClasse -> numCompetence( i + 1) );
	  debug() << "Compétence : " << tmp.nom() << ", valeur : "
		  << mClasse -> numCompetence( i + 1) << endmsg;
	  anciennesVal.push_back( mClasse -> numCompetence( i + 1) );
	  total += mClasse -> numCompetence( i + 1);
	  connect( valeurs.back(), SIGNAL( valueChanged(int) ),
		   this, SLOT( changerValeur() ) );
	  dimension++;
	  i++;
	}
    }

  for (i = 0; i < dimension; i++)
    {
      boiteLayout -> addWidget( labels[i], i, 0 );
      boiteLayout -> addWidget( valeurs[i], i, 1 );
    }

  boite -> setLayout( boiteLayout );

  func() << "AugPourcent::prepareAffichage -> fin" << endmsg;
  /*Debug::*/depileNiveau();
}

/**
 * Méthode gérant la création et la connection des boutons avec les
 * slots de BaseDialog.
 *
 * Evite la duplication de code entre les différents constructeurs.
 *
 * Le niveau de sortie est paramétré par BaseDialog::interne :\n
 * - \e FUNC  affiche les messages de début et de fin de méthode.\n
 */
void AugPourcent::prepareBoutons()
{
  /*Debug::*/empileNiveau( &interne );
  func() << "AugPourcent::prepareBoutons -> début" << endmsg;

  boutons.push_back( new QPushButton( trUtf8("&Quitter"), this ) );
  boutons.back() -> setToolTip( trUtf8("Quitter le programme") );
  connect( boutons.back(), SIGNAL( clicked() ), this, SLOT( annuler() ) );
  boutons.push_back( new QPushButton( trUtf8("&OK"), this ) );
  boutons.back() -> setToolTip( trUtf8("Accepter et continuer") );
  connect( boutons.back() , SIGNAL( clicked() ), this, SLOT( fermer() ) );

  func() << "AugPourcent::prepareBoutons -> fin" << endmsg;
  /*Debug::*/depileNiveau();
}

/**
 * Recalcule le nombre de points disponible à chaque changement de
 * valeur d'une compétence, et met à jour l'affichage du nombre de
 * points restants.\n
 *
 * On ne modifie pas la valeur PP, mais on modifie la valeur affichée
 * par la somme des changements effectués.
 */
void AugPourcent::changerValeur()
{
  int newTot(0);

  for (unsigned int i(0); i < dimension; i++)
    {
      newTot += anciennesVal[i] - valeurs[i] -> value();
    }

  nbrPP -> display( PP + newTot );
}

/**
 * On redéfinit la méthode fermer(), car on veut obliger le joueur à
 * utiliser tous les points qu'il a à disposition.
 *
 * Le niveau de sortie est paramétré par BaseDialog::interne :\n
 * - \e FUNC affiche les messages de début et de fin de méthode.\n
 * - \e LINFO affiche le récapitulatif des changements.\n
 * - \e DEBUG affiche le nombre de compétences originales et la
 * taille du conteneur temporaire.
 */
void AugPourcent::fermer()
{
  /*Debug::*/empileNiveau( &interne );
  func() << "AugPourcent::fermer -> début" << endmsg;

  OK = true;

  if ( PP < 0 ) return;
  if ( PP > 0 ) return;

  unsigned int taille( mClasse -> tailleCompetences() ), comp;

  vector<unsigned int> tmpCompetences;

  for (unsigned int i(0), j(0); i < taille; i++)
    {
      comp = mClasse -> numCompetence( i );
      if ( mClasse -> competenceNumero( comp ).pourcentage() )
	{
	  tmpCompetences.push_back( comp );
	  tmpCompetences.push_back( valeurs[j] -> value() );
	  j++;
	  i++;
	}
      else
	tmpCompetences.push_back( comp  );
    }

  for (unsigned int i(0); i < taille; i++)
    {
      linfo() << mClasse -> numCompetence( i ) << " -> " 
	      << tmpCompetences[i] << endmsg;
    }

  debug() << "Avant, taille : " << taille << ", après taille : "
	  << tmpCompetences.size() << endmsg;

  mClasse -> setCompetences( tmpCompetences );

  close();

  func() << "AugPourcent::fermer -> fin" << endmsg;
  /*Debug::*/depileNiveau();
}
